﻿using System;
using System.Data.Linq;
using System.Linq;
using RuTracker.Interface;
using RuTrackerLib.ServiceAttibutes;

namespace RuTracker.WebSite.DbLayer.Repositories
{
    [PerThreadService]
    public class UserRepository : IUserRepository
    {
        private readonly DataClassesDataContext _context;

        public UserRepository(IDbLayerSettings settings)
            : this(new DataClassesDataContext(settings.ConnectionString))
        {
            
        }

        protected UserRepository(DataClassesDataContext context)
        {
            _context = context;
        }

        public bool IsUserRegistered(string name)
        {
            return GetUser(name) != null;
        }

        public User GetUser(string name)
        {
            return _context.Users.FirstOrDefault(u => u.Name == name);
        }

        public User CreateUser(string name, string password, string email)
        {
            if (IsUserRegistered(name))
                throw new ArgumentException(string.Format("User with name: {0} is already registered", name));

            _context.Users.InsertOnSubmit(new User { CreationDate = DateTime.Now, EMail = email, Name = name, Password = password});
            CommitChanges();
            return GetUser(name);
        }

        public void UpdateUser(User user)
        {
            CommitChanges();
        }

        public void SetUserStorageInfo(string userName, string storageFolder, byte[] token)
        {
            User user = GetUser(userName);
            if (user == null)
                throw new ArgumentException(string.Format("User with name: {0} is none registered", userName));

            ClearStorageInfos(userName);

            UserStorageInfo userStorageInfo = new UserStorageInfo
            {
                User = user,
                StorageFolder = storageFolder,
                Token = token
            };

            _context.UserStorageInfos.InsertOnSubmit(userStorageInfo);
            CommitChanges();
        }

        public UserStorageInfo GetUserStorageInfo(string userName)
        {
            return _context.UserStorageInfos.Where(usi => usi.User.Name == userName)
                .OrderByDescending(usi => usi.Id).FirstOrDefault();
        }

        public void DownloadTorrent(string userName, string torrentUrl)
        {
            User user = GetUser(userName);
            UserTorrent torrent = _context.UserTorrents.FirstOrDefault(ut => ut.User.Name == userName && ut.TopicUrl == torrentUrl);
            if (torrent != null)
                torrent.DownloadedDate = DateTime.Now;
            else
                _context.UserTorrents.InsertOnSubmit(new UserTorrent { DownloadedDate = DateTime.Now, TopicUrl = torrentUrl, User = user});

            CommitChanges();
        }

        public UserTorrent GetUserTorrent(string userName, string torrentUrl)
        {
            return _context.UserTorrents.FirstOrDefault(x => x.User.Name == userName && string.Compare(x.TopicUrl, torrentUrl, StringComparison.InvariantCultureIgnoreCase) == 0);
        }

        public void Dispose()
        {
            CommitChanges();
            _context.Dispose();
        }

        private void ClearStorageInfos(string user)
        {
            _context.UserStorageInfos.DeleteAllOnSubmit(_context.UserStorageInfos.Where(u => u.User.Name == user));
        }

        private void CommitChanges()
        {
            _context.SubmitChanges(ConflictMode.ContinueOnConflict);
        }
    }
}
